package com.nabicht.bigblankpage.gui;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;

import com.nabicht.utilities.DocumentManager.AbstractDocumentManager;
import com.nabicht.utilities.DocumentManager.ManagedDocument;
import com.nabicht.utilities.printing.BasicPrinting;


public class BBPDocument implements ManagedDocument, Printable {

	private File file = null;
	private BBPFrame frame = null;
	private BBPPanel panel = new BBPPanel();
	private NameChanger nameChanger = null;
	
	public BBPDocument(File file, AbstractDocumentManager docManager) {
		//TODO make sure file is writeable and throw exception if not
		//TODO make sure file is not directory and throw exception if is directory
		//TODO make sure file exists and throw exception if not
		//TODO make sure file is not null and throw exception if it is
		frame = new BBPFrame(this);
		setFile(file, docManager);
		load();
	}
	
	public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
		Font font = getPanel().getFont();
		String text = getPanel().getText();
		return BasicPrinting.printText(text, font, graphics, pageFormat, pageIndex);
	}
	
	public BBPFrame getFrame() {
		return frame;
	}
	
	
	public void setFile(File file, AbstractDocumentManager docManager) {
		this.file = file;
		String fileName = file.getName();
		if (docManager.isGeneratedFileName(fileName)) {
			nameChanger = new NameChanger(this);
			getPanel().getDocument().addDocumentListener(nameChanger);
			getFrame().setDocumentName(nameChanger.getName());
		} else {
			frame.setDocumentName(fileName);
			if (nameChanger != null) {
				getPanel().getDocument().removeDocumentListener(nameChanger);
			}
		}
	}
	
	public void addKeyListener(KeyListener kl) {
		panel.addKeyListener(kl);
	}
	
	public void removeKeyListener(KeyListener kl) {
		panel.removeKeyListener(kl);
	}
	
	private void load() {
		StringBuffer sb = new StringBuffer();
		try{
			
			BufferedReader br = new BufferedReader(new FileReader(file));
			String strLine;
			//Read File Line By Line
			boolean newline = false;
			while ((strLine = br.readLine()) != null)   {
				if (newline) {
					sb.append(System.getProperty("line.separator"));	
				} else {
					newline = true;
				}
				sb.append(strLine);
			}
			br.close();
		}catch (Exception e){
			//TODO I need to do something here other than printing to screen
			System.err.println("Error opening file: " + file.getName());
			e.printStackTrace();
		}
		panel.setVisible(false);
		panel.setText(sb.toString());
		panel.placeCaretAtEnd();
		panel.setVisible(true);
	}
	
	public void save() {
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(file));
			bw.write(panel.getText());
			bw.close();
		} catch (FileNotFoundException fnfe) {
			System.err.println("Problem saving file: " + file.getName());
			fnfe.printStackTrace();
			//TODO something else here other than just printing
		} catch (IOException ioe) {
			System.err.println("Problem saving file: " + file.getName());
			ioe.printStackTrace();
			//TODO something else here other than just printing
		}

	}
	
	
	public boolean hasBeenChanged() {
		//TODO implement properly
		return true;
	}
	
	public void repaint() {
		if (panel != null) {
			panel.repaint();
		}
 		if (frame != null) {
			frame.repaint();
		}
	}
	
	
	public BBPPanel getPanel() {
		return panel;
	}
	
	public File getFile() { 
		return file; 
	}
	
	public void print() {
		getPanel().print();
	}
	
	
	
    
    private class NameChanger implements DocumentListener {
    	
    	private String name = "";
    	
    	private BBPDocument doc;
    	
    	public NameChanger(BBPDocument doc) {
    		this.doc = doc;
    		name = generateName();
    	}
    	
    	private String generateName() {
    		String lineSep = System.getProperty("line.separator");
    		String n = "";
    		try {
    			n = doc.getPanel().getDocument().getText(0, 100);
    		} catch (BadLocationException ble) {
    			n = doc.getPanel().getText();
    		}
    		n = n.replaceAll(lineSep, " ").trim();
    		int len = n.length();
			n = n.substring(0, len < 50 ? len : 50); 
    		if (n.length() == 0) {
    			return "Empty Document";
    		}
    		if (n.length() < 50) {
    			return n;
    		}
    		return n + "...";
    	}
    	
    	public String getName() {
    		return name;
    	}
    	
    	private void changeName() {
    		String newName = generateName();
    		if (newName.equals(name)) return;
    		name = newName;
    		doc.getFrame().setDocumentName(name);
    		
    	}
    	
    	public void insertUpdate(DocumentEvent e) {
    		changeName();
        }
    	
        public void removeUpdate(DocumentEvent e) {
        	changeName();
        }
        
        public void changedUpdate(DocumentEvent e) {
            //Plain text components don't fire these events
        }
    }
    
}
